package org.dromara.iot.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.GlobalConstants;
import org.dromara.common.core.enums.DeviceStatus;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.websocket.enums.MessageType;
import org.dromara.common.websocket.event.BoardWebSocketMessageEvent;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.dromara.iot.domain.DeviceEvent;
import org.dromara.iot.domain.bo.IotElevatorBo;
import org.dromara.iot.domain.vo.IotElevatorVo;
import org.dromara.iot.enums.BusinessCodeEnum;
import org.dromara.iot.enums.DeviceElevatorEventTypeEnum;
import org.dromara.iot.service.IIotElevatorService;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.dromara.iot.domain.bo.IotElevatorEventBo;
import org.dromara.iot.domain.vo.IotElevatorEventVo;
import org.dromara.iot.domain.IotElevatorEvent;
import org.dromara.iot.mapper.IotElevatorEventMapper;
import org.dromara.iot.service.IIotElevatorEventService;

import java.util.List;
import java.util.Map;
import java.util.Collection;

/**
 * 电梯事件Service业务层处理
 *
 * @author lsl
 * @date 2025-04-16
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class IotElevatorEventServiceImpl implements IIotElevatorEventService {

    private final IotElevatorEventMapper baseMapper;
    private final IIotElevatorService iotElevatorService;

    /**
     * 查询电梯事件
     */
    @Override
    public IotElevatorEventVo queryById(Long eventId) {
        return baseMapper.selectVoById(eventId);
    }

    /**
     * 查询电梯事件列表
     */
    @Override
    public TableDataInfo<IotElevatorEventVo> queryPageList(IotElevatorEventBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<IotElevatorEvent> lqw = buildQueryWrapper(bo);
        Page<IotElevatorEventVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        List<IotElevatorEventVo> records = result.getRecords();
        List<Long> elevatorIds = records.stream().map(IotElevatorEventVo::getElevatorId).toList();
        if (records.isEmpty()) {
            return TableDataInfo.build(result);
        }
        List<IotElevatorVo> iotElevators = iotElevatorService.queryByIds(elevatorIds);
        records.forEach(record -> record.setElevator(iotElevators.stream().filter(elevator -> elevator.getElevatorId().equals(record.getElevatorId())).findFirst().orElse(null)));
        return TableDataInfo.build(result);
    }

    /**
     * 查询电梯事件列表
     */
    @Override
    public List<IotElevatorEventVo> queryList(IotElevatorEventBo bo) {
        LambdaQueryWrapper<IotElevatorEvent> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<IotElevatorEvent> buildQueryWrapper(IotElevatorEventBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<IotElevatorEvent> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getElevatorId() != null, IotElevatorEvent::getElevatorId, bo.getElevatorId());
        lqw.eq(StringUtils.isNotBlank(bo.getEventCode()), IotElevatorEvent::getEventCode, bo.getEventCode());
        lqw.like(StringUtils.isNotBlank(bo.getElevatorName()), IotElevatorEvent::getElevatorName, bo.getElevatorName());
        lqw.eq(StringUtils.isNotBlank(bo.getUseUnit()), IotElevatorEvent::getUseUnit, bo.getUseUnit());
        lqw.eq(StringUtils.isNotBlank(bo.getServerUnit()), IotElevatorEvent::getServerUnit, bo.getServerUnit());
        lqw.eq(bo.getEventType() != null, IotElevatorEvent::getEventType, bo.getEventType());
        lqw.eq(bo.getReportTime() != null, IotElevatorEvent::getReportTime, bo.getReportTime());
        lqw.eq(bo.getRemoveTime() != null, IotElevatorEvent::getRemoveTime, bo.getRemoveTime());
        lqw.ge(bo.getStartTime() != null, IotElevatorEvent::getReportTime, bo.getStartTime());
        lqw.le(bo.getEndTime() != null, IotElevatorEvent::getReportTime, bo.getEndTime());
        lqw.orderByDesc(IotElevatorEvent::getReportTime);
        return lqw;
    }

    /**
     * 新增电梯事件
     */
    @Override
    public Boolean insertByBo(IotElevatorEventBo bo, boolean isReport) {
        if (isReport) {
            WebSocketUtils.publishAll(bo.getRemark());
        }
        IotElevatorEvent add = MapstructUtils.convert(bo, IotElevatorEvent.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setEventId(add.getEventId());
        }
        return flag;
    }

    /**
     * 修改电梯事件
     */
    @Override
    public Boolean updateByBo(IotElevatorEventBo bo) {
        IotElevatorEvent update = MapstructUtils.convert(bo, IotElevatorEvent.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(IotElevatorEvent entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除电梯事件
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 查询电梯事件数量
     */
    @Override
    public Long queryWarningCount(IotElevatorEventBo bo) {
        LambdaQueryWrapper<IotElevatorEvent> lqw = buildQueryWrapper(bo);
        lqw.ne(IotElevatorEvent::getEventType, 0);
        return baseMapper.selectCount(lqw);
    }

    @Override
    public void deleteByReportTime(Integer saveDays) {
        LambdaQueryWrapper<IotElevatorEvent> lqw = Wrappers.lambdaQuery();
        lqw.le(IotElevatorEvent::getReportTime, DateUtils.getNowDate().getTime() - saveDays * 24 * 60 * 60 * 1000)
                .eq(IotElevatorEvent::getEventType, 0);
        baseMapper.delete(lqw);
    }

    @Override
    public TableDataInfo<IotElevatorEventVo> queryWarningList(IotElevatorEventBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<IotElevatorEvent> lqw = buildQueryWrapper(bo);
        lqw.ne(IotElevatorEvent::getEventType, 0);
        lqw.ne(IotElevatorEvent::getEventType, 3);
        Page<IotElevatorEventVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }
    
    /**
     * 属性继承
     */
    @EventListener(BoardWebSocketMessageEvent.class)
    public void onEvent(BoardWebSocketMessageEvent e) {
        log.info("收到事件：{}", e.getBoardWebSocketMessage());
        MessageType messageType = e.getBoardWebSocketMessage().getMessageType();
        IotElevatorVo iotElevator = iotElevatorService.selectByRegisteredCode(e.getBoardWebSocketMessage().getBoardId());
        if (iotElevator == null) {
            return;
        }
        String event = RedisUtils.getCacheObject(GlobalConstants.CAMERA_KEY + iotElevator.getIdentifyCode() + ":" + DeviceElevatorEventTypeEnum.TIMED_REPORT.getCode());
        DeviceEvent deviceEvent = JSONUtil.toBean(event, DeviceEvent.class);
        if (deviceEvent == null) {
            return;
        }
        IotElevatorEventBo iotElevatorEvent = deviceEvent.toIotElevatorEvent();
        if (MessageType.ONLINE.equals(messageType)) {
            //设备上线
            log.info("电梯设备上线：{}", iotElevator.getRegisteredCode());
            iotElevator.setStatus(DeviceStatus.ONLINE.getStatus());
            iotElevatorEvent.setRemark(iotElevator.getElevatorName() + ":上线");
        } else if (MessageType.OFFLINE.equals(messageType)) {
            //设备下线
            log.info("电梯设备下线：{}", iotElevator.getRegisteredCode());
            iotElevator.setStatus(DeviceStatus.OFFLINE.getStatus());
            iotElevatorEvent.setRemark(iotElevator.getElevatorName() + ":下线");
        }
        iotElevator.setAnnualDate(DateUtils.getNowDate());
        iotElevatorService.updateByBo(BeanUtil.toBean(iotElevator, IotElevatorBo.class));
        iotElevatorEvent.setEventCode(BusinessCodeEnum.ELEVATOR_EVENT.getBusinessCode());
        iotElevatorEvent.setEventType(DeviceElevatorEventTypeEnum.OFFLINE_ONLINE_EVENT.getCode());
        iotElevatorEvent.setElevatorId(iotElevator.getElevatorId());
        iotElevatorEvent.setElevatorName(iotElevator.getElevatorName());
        iotElevatorEvent.setUseUnit(iotElevator.getUseUnit());
        iotElevatorEvent.setServerUnit(iotElevator.getMaintenanceUnit());
        this.insertByBo(iotElevatorEvent, true);
    }
}
